#ifndef __SOR__
#define __SOR__

#include <vector>
#include <fstream>
#include <iostream>
#include <math.h>
using namespace std;

typedef std::vector<double> vectorXd;

class sparsematrix{
 public:
  int n;
  int nzn;
  vector<int> row;
  vector<int> col;
  vector<double> element;

  sparsematrix(){};
 sparsematrix(int _n, int _nzn):n(_n),nzn(_nzn){
    row.resize(nzn);
    col.resize(nzn);
    element.resize(nzn);
  };

  int read(std::ifstream &input){
    int i,j,z=0;
    double a;
    while(input >> i){
      input >> j;
      input >> a;
      row[z] = j;
      col[z] = i;
      element[z] = a;
      z++;
    }
    return 0;
  };

void display(){
    for(int i = 0; i < nzn; i++)
      cout << "(" << row[i] << "," << col[i] << ") " << element[i] << endl;
  }
};

void SorIterative(sparsematrix & M, vectorXd & b, double w, vectorXd & x){
  for(int z = 0; z < M.nzn; z++){
    int first = M.row[z];
    double dot = 0.0;
    double d;
    while(z != M.nzn && M.row[z] == first){
	if(M.row[z] != M.col[z]){
	  dot += M.element[z] * x[M.col[z] - 1];
	}
	else{
	  d = M.element[z];
	}
	++z;
      }
      --z;
      double y = (b[first-1] - dot) / d;
      x[first-1] = x[first-1] + w * (y - x[first-1]);
  }
};

double infiniteNorm(vectorXd & x){
  double norm = 0.0;
  for(auto it = x.begin(); it != x.end(); ++it){
    if(fabs(*it) > norm){
      norm = fabs(*it);
    }
  }
  return norm;
};

bool convence(vectorXd & x, vectorXd y, double epsilon){
  for(auto it = y.begin(), it1 = x.begin(); it != y.end(), it1 != x.end(); ++it, ++it1){
    *it = *it1 - *it;
  }
  return (infiniteNorm(y) < epsilon);
};



#endif
  
